parser grammar Analexparser;

options {
  language = Java;
  tokenVocab = Analexlexer;
  backtrack = true;
}

@header {
  package practpl.siete;
}

@members {
     private ArrayList<RecognitionException> errors = new ArrayList<RecognitionException>();
     public ArrayList<RecognitionException> getErrors() {
        return errors;
     }
     @Override
     public void reportError (RecognitionException e) {
        String msg = getErrorMessage(e, getTokenNames());
        System.err.println(msg);
        errors.add(e);
     }
}

yacc: definiciones SEPARADOR gramatica SEPARADOR proc_auxiliares;

//DEFINICIONES
definiciones: ABRE_DCC incluye* typedef* (declaracion PUNTOCOMA)* CIERRA_DCC (simboloinicial|token|tipo|union|left)*;
incluye: INCLUDE LIBRERIA;
typedef: IDENT IDENT INTERVAL LLAVEA (declaracion PUNTOCOMA)* LLAVEC INTERVAL PUNTOCOMA;
declaracion: (tipodedato|IDENT|INTERVAL) IDENT (PARENTA PARENTC | corchetes)? (COMA IDENT (PARENTA PARENTC | corchetes)?)*;
tipodedato: (DOUBLE|CHAR);
simboloinicial: PORCENTAJE START IDENT;
token: PORCENTAJE TOKEN ETIQUETA IDENT*;
tipo: PORCENTAJE TYPE ETIQUETA IDENT*;
union: PORCENTAJE UNION LLAVEA (declaracion PUNTOCOMA)* LLAVEC;
left: PORCENTAJE LEFT ((COMILLASIMPLE operadores COMILLASIMPLE) | IDENT)* ;

operadores: (MAS|MENOS|MULT|DIV);
corchetes: (CORCHETEA DOLAR? (IDENT|NUMERO|ALGO|operadores)* CORCHETEC);


//GRAMATICA
gramatica: (noterminal COLON regla? (OR regla)* PUNTOCOMA)*;
noterminal: IDENT;
codigoC : LLAVEA ((((IDENT (corchetes)? ((PARENTA (CADENA | dolar_) (COMA (CADENA|dolar_))* PARENTC) | (IGUAL dolar_))?) | (dobledolar)) PUNTOCOMA?) | sentenciaif )* LLAVEC;
dobledolar: DOLAR DOLAR (ALGO)? (IGUAL ((DOLAR dolar_) | llamadafuncion PUNTOCOMA | (IDENT corchetes) | ((MENOS)? dolar_ (operadores dolar_)?)))*;
regla: (regla1|regla2|regla3) codigoC?;

regla1: IDENT (IDENT|saltolinea)*;
regla2: IDENT COMILLASIMPLE (IGUAL|operadores) COMILLASIMPLE (IDENT|saltolinea)*;
regla3: COMILLASIMPLE (parentesis|operadores) COMILLASIMPLE ((COMILLASIMPLE (parentesis|operadores|COMA) COMILLASIMPLE) |IDENT|PORCENTAJE)*;

saltolinea: COMILLASIMPLE BARRA N COMILLASIMPLE;
parentesis: (PARENTA | PARENTC);
dolar_: DOLAR (ALGO|NUMERO);

sentenciaif: IF PARENTA (comparadobledolar|llamadafuncion) PARENTC (llamadafuncion PUNTOCOMA | (LLAVEA (llamadafuncion PUNTOCOMA)* LLAVEC));
comparadores: (MENOR | MAYOR | MENORIGUAL | MAYORIGUAL | COMPARA | DISTINTO);
comparadobledolar: dobledolar comparadores dobledolar;

llamadafuncion: IDENT (PARENTA ((CADENA|dolar_|IDENT|ALGO) (COMA (CADENA|dolar_|IDENT|ALGO))*)? PARENTC)?;

//PROCEDIMIENTOS AUXILIARES
proc_auxiliares: constante* (definicionfuncion|ifnuevo|buclefor)* intervalos+;
constante: DEFINE IDENT (NUMERO|IDENT);
retorno: RETURN PARENTA (llamadafuncion|CARACTER|NUMERO|IDENT) PARENTC;
definicionfuncion: IDENT PARENTA PARENTC LLAVEA (((declaracion|retorno) PUNTOCOMA)|ifnuevo|buclewhile)* LLAVEC;
buclewhile: WHILE PARENTA (NUMERO|IDENT|(PARENTA asignacion PARENTC)) comparadores (IDENT|NUMERO|(COMILLASIMPLE COMILLASIMPLE)) PARENTC (sentenciasbucle|(LLAVEA (sentenciasbucle)* LLAVEC));
asignacion: (ALGO|IDENT) (COMA IDENT)* IGUAL (ALGO|NUMERO|(IDENT operadores CARACTER)|(IDENT (PARENTA (IDENT)? PARENTC)?)|CARACTER|(COMILLASIMPLE BARRA NUMERO COMILLASIMPLE))*;
ifnuevo: IF PARENTA (llamadafuncion| OR2 | AND | comparacion)* PARENTC (sentenciasbucle|(LLAVEA (sentenciasbucle)* LLAVEC)) (ELSE (sentenciasbucle|LLAVEA (sentenciasbucle)+ LLAVEC))?;
declasig: (tipodedato|IDENT) IDENT (PARENTA PARENTC | corchetes)? (IGUAL (NUMERO|IDENT))? COMA (IDENT|ALGO) IGUAL (NUMERO|IDENT); 
comparacion: ((PARENTA ALGO PARENTC)|IDENT) comparadores (IDENT|NUMERO|CARACTER|ALGO);
incremento: ((MAS MAS IDENT) | (IDENT MAS MAS));
decremento: ((MENOS MENOS IDENT)| (IDENT MENOS MENOS));
buclefor: FOR PARENTA asignacion? PUNTOCOMA comparacion? PUNTOCOMA (incremento | decremento) (COMA asignacion)? PARENTC
          (sentenciasbucle)|(LLAVEA (sentenciasbucle)+ LLAVEC);
sentenciasbucle: (((llamadafuncion|asignacion|declaracion|declasig|retorno|BREAK) PUNTOCOMA) | (buclefor|ifnuevo));
intervalos: INTERVAL IDENT PARENTA IDENT (COMA IDENT)* PARENTC (declaracion PUNTOCOMA)* (LLAVEA sentenciasbucle+ LLAVEC);
